/**
 *                            License
 * THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS  
 * CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). 
 * THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW.  
 * ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR  
 * COPYRIGHT LAW IS PROHIBITED.
 * 
 * BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND  
 * AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE  
 * MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED 
 * HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
 * 
 */
package l1j.server.server;

import java.sql.ResultSet; //# 검색 명령어 추가 위해 임포트 
import java.sql.PreparedStatement; //# 검색 명령어 추가 위해 임포트 
import java.util.Map;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;

import l1j.server.server.command.L1Commands;
import l1j.server.server.command.executor.L1CommandExecutor;
import l1j.server.L1DatabaseFactory; //# 검색 명령어 추가 위해 임포트 
import l1j.server.server.datatables.AutoLoot; //# 오토루팅 명령어..
import l1j.server.server.datatables.ItemTable;
import l1j.server.server.model.Instance.L1PcInstance;
import l1j.server.server.serverpackets.S_ServerMessage;
import l1j.server.server.serverpackets.S_SystemMessage;
import l1j.server.server.templates.L1Command;
import l1j.server.server.templates.L1Item;
import l1j.server.server.utils.collections.Maps;

// Referenced classes of package l1j.server.server:
// ClientThread, Shutdown, IpTable, MobTable,
// PolyTable, IdFactory
//

/**
 * GM指令
 */
public class GMCommands {

	private static Logger _log = Logger.getLogger(GMCommands.class.getName());

	private static GMCommands _instance;

	private GMCommands() {
	}

	public static GMCommands getInstance() {
		if (_instance == null) {
			_instance = new GMCommands();
		}
		return _instance;
	}

	private String complementClassName(String className) {
		// 如果包涵 . 则认为他已经有完整路径，所以直接丢回去
		if (className.contains(".")) {
			return className;
		}

		// 如果没有点的话则自动帮他补完前面的路径
		return "l1j.server.server.command.executor." + className;
	}

	private boolean executeDatabaseCommand(L1PcInstance pc, String name,
			String arg) {
		try {
			L1Command command = L1Commands.get(name);
			if (command == null) {
				return false;
			}
			if (pc.getAccessLevel() < command.getLevel()) {
				pc.sendPackets(new S_ServerMessage(74, "커멘드" + name)); 
				return true;
			}

			Class<?> cls = Class.forName(complementClassName(command
					.getExecutorClassName()));
			L1CommandExecutor exe = (L1CommandExecutor) cls.getMethod(
					"getInstance").invoke(null);
			exe.execute(pc, name, arg);
			_log.info(pc.getName() + "가." + name + " " + arg + "커멘드를 사용했습니다.");
			return true;
		} catch (Exception e) {
			_log.log(Level.SEVERE, "error gm command", e);
		}
		return false;
	}

	/** 处理GM指令 */
	public void handleCommands(L1PcInstance gm, String cmdLine) {
		StringTokenizer token = new StringTokenizer(cmdLine);
		// 命令，直到第一个空白，并在其后当作参数空格隔开
		String cmd = token.nextToken();
		String param = "";
		while (token.hasMoreTokens()) {
			param = new StringBuilder(param).append(token.nextToken())
					.append(' ').toString();
		}
		param = param.trim();

		// 将使用过的指令存起来
		if (executeDatabaseCommand(gm, cmd, param)) {
			if (!cmd.equalsIgnoreCase("r")) {
				_lastCommands.put(gm.getId(), cmdLine);
			}
			return;
		}
		if (gm.getAccessLevel() < 200) {
			gm.sendPackets(new S_ServerMessage(74, "커멘드" + cmd)); 
			return;
	   		   
			//# 오토루팅 명령어..
		} else if (cmd.equalsIgnoreCase("오토루팅")) { 
			autoloot(gm, param);
			//# ..
		}
		if (cmd.equalsIgnoreCase("r")) {
			if (!_lastCommands.containsKey(gm.getId())) {
				gm.sendPackets(new S_ServerMessage(74, "指令 " + cmd)); // \f1%0%o 无法使用。
				return;
			}
			redo(gm, param);
			return;
		}
		//		gm.sendPackets(new S_SystemMessage("커멘드 " + cmd + " 는 존재하지 않습니다."));
	}
	//# 오토루팅 명령어..
	private void autoloot(L1PcInstance gm, String param)
	{
		try {
			StringTokenizer tok = new StringTokenizer(param);
			String type = tok.nextToken();
			if (type.equalsIgnoreCase("리로드")) {
				AutoLoot.getInstance().reload();
				gm.sendPackets(new S_SystemMessage("오토루팅 설정이 리로드 되었습니다."));
			} else if (type.equalsIgnoreCase("검색")) {
				java.sql.Connection con = null;
				PreparedStatement pstm = null;
				ResultSet rs = null;

				String nameid = tok.nextToken(); 
				try {
					con = L1DatabaseFactory.getInstance().getConnection();
					String strQry;
					strQry = " Select e.item_id, e.name from etcitem e, autoloot l where l.item_id = e.item_id and name Like '%" + nameid + "%' ";
					strQry += " union all " + " Select w.item_id, w.name from weapon w, autoloot l where l.item_id = w.item_id and name Like '%" + nameid + "%' ";
					strQry += " union all " + " Select a.item_id, a.name from armor a, autoloot l where l.item_id = a.item_id and name Like '%" + nameid + "%' ";
					pstm = con.prepareStatement(strQry);
					rs = pstm.executeQuery();
					while (rs.next()) {
						gm.sendPackets(new S_SystemMessage("[" + rs.getString("item_id") + "] " + rs.getString("name")));
					}
				} catch (Exception e) {
				} finally {
					rs.close();
					pstm.close();
					con.close();
				}
			} else {
				String nameid = tok.nextToken();
				int itemid = 0;
				try {
					itemid = Integer.parseInt(nameid);
				} catch (NumberFormatException e) {
					itemid = ItemTable.getInstance().findItemIdByNameWithoutSpace(nameid);
					if (itemid == 0) {
						gm.sendPackets(new S_SystemMessage("해당 아이템이 발견되지 않습니다. "));
						return;
					}
				}

				L1Item temp = ItemTable.getInstance().getTemplate(itemid);
				if (temp == null) {
					gm.sendPackets(new S_SystemMessage("해당 아이템이 발견되지 않습니다. "));
					return;
				}

				if (type.equalsIgnoreCase("추가")) {
					if (AutoLoot.getInstance().isAutoLoot(itemid)) {
						gm.sendPackets(new S_SystemMessage("이미 오토루팅 목록에 있습니다."));
						return;
					}
					AutoLoot.getInstance().storeId(itemid);
					gm.sendPackets(new S_SystemMessage("오토루팅 항목에 추가 했습니다."));
				} else if (type.equalsIgnoreCase("삭제")) {
					if (!AutoLoot.getInstance().isAutoLoot(itemid)) {
						gm.sendPackets(new S_SystemMessage("오토루팅 항목에 해당 아이템이 없습니다."));
						return;
					}
					gm.sendPackets(new S_SystemMessage("오토루팅 항목에서 삭제 했습니다."));
					AutoLoot.getInstance().deleteId(itemid);
				}
			}
		} catch (Exception e) {
			gm.sendPackets(new S_SystemMessage(".오토루팅 리로드"));
			gm.sendPackets(new S_SystemMessage(".오토루팅 추가|삭제 itemid|name"));
			gm.sendPackets(new S_SystemMessage(".오토루팅 검색 name"));
		}
	}

	private static Map<Integer, String> _lastCommands = Maps.newMap();

	private void redo(L1PcInstance pc, String arg) {
		try {
			String lastCmd = _lastCommands.get(pc.getId());
			if (arg.isEmpty()) {
				pc.sendPackets(new S_SystemMessage("커멘드 " + lastCmd
						+ " (을)를 재실행합니다"));
				handleCommands(pc, lastCmd);
			} else {
				
				StringTokenizer token = new StringTokenizer(lastCmd);
				String cmd = token.nextToken() + " " + arg;
				pc.sendPackets(new S_SystemMessage("커멘드 " + cmd + " 를 실행합니다."));
				handleCommands(pc, cmd);
			}
		} catch (Exception e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
			pc.sendPackets(new S_SystemMessage(".r 커멘드 에러"));
		}
	}
}
